using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Test;
using IdentityServer4.Validation;
using Idp_Login.DbModel;
using Idp_Login.Service;
using Microsoft.AspNetCore.Authentication;
using Microsoft.VisualBasic;

namespace Idp_Login
{
    //1.“如何使用已有用户数据自定义Claim”，实现 IResourceOwnerPasswordValidator 是为了对接已有的用户数据
    //这两步共同完成的是 “使用已有用户数据自定义Claim”，并不是自定义 Claim 就非得把两个都实现。

    /// <summary>
    /// 自定义 Resource owner password 验证器(自定义用户校验)
    /// </summary>
    public class CustomResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
    {

        ///// <summary>
        ///// 这里为了演示我们还是使用TestUser作为数据源，
        ///// 正常使用此处应当传入一个 用户仓储 等可以从
        ///// 数据库或其他介质获取我们用户数据的对象
        ///// </summary>
        //private readonly TestUserStore _users;
        //private readonly ISystemClock _clock;


        //public CustomResourceOwnerPasswordValidator(TestUserStore users, ISystemClock clock)
        //{
        //_users = users;
        //_clock = clock;
        //}

        private readonly IAdminService _adminService;

        public CustomResourceOwnerPasswordValidator(IAdminService adminService)
        {
            this._adminService = adminService;
        }

        /// <summary>
        /// 验证
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            bool 内置用户 = false;

            if (内置用户)
            {
                ////此处使用context.UserName, context.Password 用户名和密码来与数据库的数据做校验
                //if (_users.ValidateCredentials(context.UserName, context.Password))
                //{
                //    var user = _users.FindByUsername(context.UserName);

                //    //验证通过返回结果 
                //    //subjectId 为用户唯一标识 一般为用户id
                //    //authenticationMethod 描述自定义授权类型的认证方法 
                //    //authTime 授权时间
                //    //claims 需要返回的用户身份信息单元 此处应该根据我们从数据库读取到的用户信息 添加Claims 如果是从数据库中读取角色信息，那么我们应该在此处添加 此处只返回必要的Claim
                //    context.Result = new GrantValidationResult(
                //        user.SubjectId ?? throw new ArgumentException("Subject ID not set", nameof(user.SubjectId)),
                //        OidcConstants.AuthenticationMethods.Password, _clock.UtcNow.UtcDateTime,
                //        user.Claims);
                //}
                //else
                //{
                //    //验证失败
                //    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,"invalid custom credential");
                //}
            }
            else
            {

                //获得postman 发送的其他数据 

                //var OtherPararm = context.Request.Raw.GetValues("OtherPararm")?.First();//比如租户id什么的
                //var tenantCode = context.Request.Raw.GetValues("tenantCode")?.First();//比如租户id什么的

                Admin user = _adminService.GetByUserNameAndPwd(context.UserName, context.Password).Result;

                if (user == null)
                {
                    //验证失败
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential");
                }
                else
                {

                    //验证通过返回结果 
                    //subjectId 为用户唯一标识 一般为用户id
                    //authenticationMethod 描述自定义授权类型的认证方法 
                    //authTime 授权时间
                    //claims 需要返回的用户身份信息单元 此处应该根据我们从数据库读取到的用户信息 添加Claims 如果是从数据库中读取角色信息，那么我们应该在此处添加 此处只返回必要的Claim


                    //ICollection<Claim> Claims = new List<Claim>()
                    //{
                    //    new Claim("userId", user.Id.ToString()),
                    //    new Claim("Phone", user?.Phone?.ToString()??""),
                    //    new Claim("Address", user?.Address?.ToString()??""),
                    //    new Claim("Email", user?.Email?.ToString()??""),
                    //    new Claim("Remark", user?.Remark?.ToString()??""),
                    //    new Claim(JwtClaimTypes.Role, "admin"),
                    //    new Claim(JwtClaimTypes.Role, "superadmin")
                    //};

                    //这边写 claims 没有用, 所以代码注释了.
                    context.Result = new GrantValidationResult(
                                    //subject: user.Id?.ToString() ?? throw new ArgumentException("Subject ID not set", nameof(user.Id)),
                                    subject: user.Id.ToString(),
                                    authenticationMethod: OidcConstants.AuthenticationMethods.Password
                                    //,DateTime.UtcNow
                                    //, Claims
                                    );
                }
            }



            return Task.CompletedTask;
        }
    }




}
